#ifndef MT_H
#define MT_H
#include <stdint.h>

#define SCHED_KERNEL_CODEDESC 	0x08
#define SCHED_KERNEL_DATADESC 	0x10
#define SCHED_KERNEL_STACKDESC 	0x10

/// http://www.osdev.org/phpBB2/viewtopic.php?t=14506&highlight=iret+lesser+privledge (XCHG)
#define SCHED_USER_CODEDESC		((8 * 4) | 3)
#define SCHED_USER_DATADESC		((8 * 5) | 3)
#define SCHED_USER_STACKDESC		((8 * 6) | 3)

#define SCHED_EFLAGS32			0x00000200
#define SCHED_EFLAGS16			0x00020202

// stack size specifier in pages.
typedef uint32_t SCHED_STACKSIZE;
// process load helper callback
typedef int(*SCHED_PLH)(void);

typedef uint32_t 	CR3;
// type definition for the context id.
typedef CR3 	CONTEXTID;
// type defintion for the process identifier.
typedef int32_t	 PROCESSID;
// type defintion for a thread identifier.
typedef int32_t	 THREADID;
// type defintion for a thread priority value.
typedef uint8_t 	SCHED_PRI;
typedef uint32_t 	ENTRYADDR;
typedef uint32_t 	STACKADDR;
typedef uint32_t	STACKSIZE;
typedef uint16_t 	SEGDESCRIPTOR;
typedef uint32_t 	EFLAGS;
typedef uint32_t	THREADFLAGS;
typedef uint32_t	MEDADDR;

typedef struct
{
	uint32_t		eax, ebx, ecx, edx, esi, edi, ebp;
	SEGDESCRIPTOR	ds, es, fs, gs, ss;
}sched_threadRegisters;
// Holds a description for the creation of a thread.
typedef struct
{
	CONTEXTID 				contextId;
	PROCESSID 				processId;
	ENTRYADDR	 			entry;
	SCHED_PRI				priority;
	STACKSIZE				kstackSize;
	STACKSIZE				ustackSize;
	SEGDESCRIPTOR			cs;
	EFLAGS				eflags;
	sched_threadRegisters		registers;
	MEDADDR				medaddr;
}sched_threadDescription;

// This is the state of any thread, and is updated as needed.
struct Tsched_thread
{
	STACKADDR	 		ustack;
	STACKADDR	 		kstack;
	CR3				cr3;
	PROCESSID 			processId;
	THREADID			threadId;
	SCHED_PRI			priority;
	THREADFLAGS			flags;
	struct Tsched_thread	*next, *prev;
};
typedef struct Tsched_thread sched_thread;

typedef struct 
{
	uint32_t 	gs, fs, es, ds;
	uint32_t 	edi, esi, ebp, esp, ebx, edx, ecx, eax;
	uint32_t 	eip, cs, eflags, _esp, ss;
}sched_stackTemplate;

#define SCHED_PRICNT 10

// adjustable array minimum free slots.
#define SCHED_THREADARRAY_FREE_MIN		20
// adjustable array maximum free slots.
#define SCHED_THREADARRAY_FREE_MAX		40

#define SCHED_THREAD_KILLED			0x1

typedef struct
{
	uint32_t 			cnt;
	sched_thread 		*active;
}sched_pri;

extern sched_thread 	*____sched_curthread;

/// @old functionality
/// -- The old functionality has been adapted to work properly with the new implementation.
// macro for stub for existing kernel intrastructure intergration
#define initmt sched_initialize
#define resched sched_switch
// function to control multi-tasking state (old)
int mtenabled();
void mtdisable();
void mtenable();
// kill the current process using the PID (old)
int kill(int pid);
// gets the current PID (old function)
int currpid();

/// @common initialization
int sched_initialize(uint32_t contextId);

/// @common functionality
THREADID sched_thread_current();
THREADID sched_thread_terminate(THREADID id);
/// create a thread. (kernel thread use zero for processID) (uses a _cdelc calling convention)
THREADID sched_create_thread(sched_threadDescription *desc, unsigned long argCount, ...);
/// performs a thread switch only if a certain amount of block ticks have passed.
void sched_switch();
/// performs a thread switch regardless of how many clock ticks have passed.
void sched_switch_core();
#endif

